#include "func.h"

//将有","与"-"的字符串转换为double型的vector
std::vector<double> func::string2list(QString str,double step){
    std::vector<double> list;
    QStringList list1=str.split(",");
    for(int i=0;i<list1.size();i++){
        if(list1[i].contains("-")){
            QStringList list2=list1[i].split("-");
            double start=list2[0].toDouble();
            double end=list2[1].toDouble();
            for(double j=start;j<=end;j+=step){
                list.push_back(j);
            }
        }
        else{
            list.push_back(list1[i].toDouble());
        }
    }
    return list;
}

void func::matchTemplate(cv::Mat const &src, cv::Mat const &templ, int method,double minScore,QString angles,QString scales, cv::Point2d &center,double &angle,double &scale,double &score){
    //将角度与缩放比例转换为double型的vector
    std::vector<double> listAngle=func::string2list(angles);
    std::vector<double> listScale=func::string2list(scales);

    //初始化
    score=0;
    angle=0;
    scale=0;

    //遍历角度与缩放比例
    for(int i=0;i<listAngle.size();i++){
        for(int j=0;j<listScale.size();j++){
            if(i>=180||i<=-180||j<=0||j>=10){
                continue;
            }
            //旋转模板
            cv::Mat templ1;
            cv::Point2f pt(templ.cols/2., templ.rows/2.);
            cv::Mat r = cv::getRotationMatrix2D(pt, listAngle[i], listScale[j]);
            cv::warpAffine(templ, templ1, r, cv::Size(templ.cols, templ.rows));
            
            //获取旋转后模板的掩码
            cv::Mat mask1;
            cvtColor(templ1, mask1, cv::COLOR_BGR2GRAY);
            threshold(mask1, mask1, 5, 255, cv::THRESH_BINARY);

            //匹配
            cv::Mat result;
            cv::matchTemplate(src, templ1, result, method, mask1);
            double minVal; double maxVal; cv::Point minLoc; cv::Point maxLoc;
            cv::Point matchLoc;
            cv::minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc, cv::Mat());
            if (method  == cv::TM_SQDIFF || method == cv::TM_SQDIFF_NORMED){
                matchLoc = minLoc;
            }
            else{
                matchLoc = maxLoc;
            }

            //保存最佳匹配
            if(maxVal>score){
                score=maxVal;
                angle=listAngle[i];
                scale=listScale[j];
                center=cv::Point2d(matchLoc.x+templ1.cols/2.,matchLoc.y+templ1.rows/2.);
            }
        }
    }

    //如果匹配分数小于最低分数,则清空匹配结果
    if(score<minScore){
        score=0;
        angle=0;
        scale=0;
        center=cv::Point2d(0,0);
    }

    return;
}

void func::matchTemplate(cv::Mat const &src, cv::Mat const &templ, int method,double minScore,QString angles,cv::Point2d &center,double &angle,double &score){
    double scale;
    func::matchTemplate(src, templ, method,minScore,angles,"1", center,angle,scale,score);
    return;
}

void func::matchTemplate(cv::Mat const &src, cv::Mat const &templ, int method,double minScore,cv::Point2d &center,double &score){
    double angle;
    func::matchTemplate(src, templ, method,minScore,"0", center,angle,score);
    return;
}

void func::rotateImage(cv::Mat &image,cv::Point2d tempCenter,double angle){
    cv::Point2f pt(tempCenter.x, tempCenter.y);
    cv::Mat r = cv::getRotationMatrix2D(pt, angle, 1.0);
    cv::warpAffine(image, image, r, cv::Size(image.cols, image.rows));
    return;
}